/* 
 * File:   Transporte.h
 * Author: superoverpower
 *
 * Created on 1 de Julho de 2011, 15:09
 */

#ifndef TRANSPORTE_H
#define	TRANSPORTE_H
#include "Layer.hpp"
using namespace ufpb::project::network;




class Transporte : public Layer {

public:
    Transporte();
    Transporte(const Transporte& orig);
    virtual ~Transporte();

    //Constantes de controle
    //Tamanho de pacote
    const static int PACOTE_LENGHT = 62;
    //Tamanho do ip de origem (recebendo) ou de destino (enviando)
    const static int IP_LENGTH = 4;
    const static int IP_OFFSET = 0;
    const static int IP_RANGE = 16;
    //Tamanho das flags indicando se e uma solicitacao de conexao
    const static int E_CON_LENGTH = 1;
    const static int E_CON_OFFSET = 4;
    const static int E_CON_RANGE = 2;
    //Tamanho das flags indicando se e uma aceitacao de conexao
    const static int E_ACK_LENGTH = 1;
    const static int E_ACK_OFFSET = 5;
    const static int E_ACK_RANGE = 2;
    //Tamanho do numero que identifica uma conexao entre mim e outro ip
    const static int ID_CON_LENGTH = 4;
    const static int ID_CON_OFFSET = 6;
    const static int ID_CON_RANGE = 16;
    //Tamanho da quantidade de pacotes de uma mensagem
    const static int NUM_PACOTES_LENGTH = 4;
    const static int NUM_PACOTES_OFFSET = 10;
    const static int NUM_PACOTES_RANGE = 16;
    //Tamanho do numero de ordem de um pacote dentro de uma mensagem completa
    const static int NUM_ORDEM_LENGTH = 4;
    const static int NUM_ORDEM_OFFSET = 10;
    const static int NUM_ORDEM_RANGE = 16;
    //Tamanho da carga de dados
    //48 bits = 6 bytes = 6 caracteres
    const static int PAYLOAD_LENGTH = 48;
    const static int PAYLOAD_OFFSET = 14;

    void newMessageToSend(Bits* dadosEnviar);
    void newReceivedMessage(Bits* dadosRecebidos);
    int getIP(Bits* data);
    int getIDConexao(Bits* data);
    int getNumPacotes(Bits* data);
    class ProcessamentoDePacoteEnviado{
        public:
            Transporte* transporte;
            ProcessamentoDePacoteEnviado(Bits* mensagemCompleta, int idConexao, Transporte *transp);
            int getIdConexao() ;
            int getNumeroDePacotes();
            int getIpDestino();
            void enviaPacotes();


        private:
            int ipDestino;
            int idConexao;
            int numPacotes;
            Bits* mensagemCompleta;
            std::vector<Bits*>* pacotes;
            void preenchePacotes();

    };

    class ProcessamentoDePacoteRecebido{
        public:
            Transporte *transporte;
            ProcessamentoDePacoteRecebido(int ipOrigem, int idConexao, int numeroDePacotes, Transporte* transp);
            int getIdConexao();
            int getIpOrigem();
            void enviaMensagemCompletaParaAplicacao();
            bool pacoteRecebido(Bits* data);

        private:
            int ipOrigem;
            int idConexao;
            int numeroDePacotes;
            bool* pacotesRecebidos;
            Bits* mensagemCompleta;
            int getNumOrdem(Bits* data);
            bool todosOsPacotesRecebidos();
            
        
    };
private:
    

    std::vector<ProcessamentoDePacoteEnviado*>* envioPendente;
    std::vector<ProcessamentoDePacoteRecebido*>* recebimentoPendente;
    int gerarIdConexao(int ipDestino);
    Bits* criarMensagemDeConexao(int ipDestino, int idConexao, int numPacotes);
    Bits* criarMensagemDeAck(int ipDestino, int idConexao);
    bool eMensagemDeAck(Bits* data);
    bool eMensagemDeConexao(Bits* data);

};

#endif	/* TRANSPORTE_H */

